iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 19
2

人生像是一列火車,旅程中總是會搭載著不同貨物,走得越遠掛載的越多,包括肥肉。

https://ithelp.ithome.com.tw/upload/images/20191004/201041759bPpG8rNEQ.png

圖片來源:www.unsplash.com / Dibyendu Sekhar Das

在法國搭高速火車時,曾經收到朋友的告誡:千萬不要自己亂換車廂,尤其是火車停在某一站的時候。

原本不以為意,但聽到以下的故事就頓時聽話了:
某人在火車停靠在某一站時,因為肚子痛急著想上廁所,但自己座位的那節車廂廁所卻有人,於是到隔壁的車廂去上,拉肚子總是不好解決,花了許多時間,等到舒緩之後,突然意會到怎麼火車還沒開,於是走回去原車廂時,驚!發現原本坐的那節車廂不見了!完全被shift()掉了!

這是真實的故事,因為法國很大,火車從巴黎出發,一路往南開會經過好幾個城市,為了節省資源,會特意在訂票時就把到達同城市的旅客集中在固定的幾節車廂,這樣一來只要到達某站,就會把指定的那幾節車廂拆卸下來(切斷),然後其餘的車廂繼續開往其他城市。反過來想,這列火車也是可以陸續和其他的車廂合併,一起開往巴黎。

火車的車廂就像是陣列,一節節的車廂合併串起來就是concat()了。 轉大人成功了

concat() 一列到達許多城市的火車

concat() 可以在陣列中與其他多個陣列合併,並回傳新的陣列。原陣列不會被改變。我們可以將要合併的陣列或元素,多個或單個,以引數的方式,讓原陣列與這些要併入的陣列或元素合併在一起。

https://ithelp.ithome.com.tw/upload/images/20191004/20104175qI0DGY793E.png

Array.prototype.concat() - JavaScript | MDN
concat() 方法
原型: Array.prototype.concat()
功能: 用來合併兩個或多個陣列或元素。concat()不會改變原有的陣列,回傳一個包含呼叫陣列本身的值,作為代替的是回傳一個新陣列。
改變: 不會改變原有的陣列
語法: var new_array = old_array.concat(value1[, value2[, ...[, valueN]]])
回傳值: 一個新的陣列實體。
參數: valueN 陣列以及/或者值,用來合併成一個新的陣列。

只要放在( )裡都吃 不偏食

我們以參數傳入的方式,把要合併的陣列或元素放在( )裡,這部分concat()非常彈性,要多個、單個、或陣列與物件的方式都可以,幾乎是給什麼吃什麼。 好雜食啊

const arr1 = ["Hi", "Wow"];

// 如果將陣列以參數傳入concat(),它會拆開這些陣列,並將元素加入原本的陣列。
const arr2 = arr1.concat([1, 2, 3]);
const arr3 = arr2.concat(4, 5, 6);
const arr4 = arr3.concat({ a: 42 });

arr1; // [ 'Hi', 'Wow' ]
arr2; // [ 'Hi', 'Wow', 1, 2, 3 ]
arr3; // [ 'Hi', 'Wow', 1, 2, 3, 4, 5, 6 ]
arr4; // [ 'Hi', 'Wow', 1, 2, 3, 4, 5, 6, { a: 42 } ]

既然是多個,我們也可以一次就把要合併的元素或物件合併上去。像這樣:

const arr1 = ["Hi", "Wow"];

const arr2 = arr1.concat([1, 2, 3], 4, 5, 6, { a: 42 });

arr1; // [ 'Hi', 'Wow' ]
arr2; // [ 'Hi', 'Wow', 1, 2, 3, 4, 5, 6, { a: 42 } ]

// 字串也可以
const colorName = "purple"
const allColor4 = [...warmColor, ...coldColor, colorName];

allColor4; // [ 'red', 'yellow', 'blue', 'gray', 'purple' ]

雖彈性也不要以為可以隨便

雖然我們可以將陣列以參數傳入concat(),它會自動拆開這些陣列,但並不表示多層的陣列就可行,要注意的是,concat()只會拆開提供給它的第一層陣列,而不會拆開第二層陣列(陣列中的陣列)。也就是說concat() 不會以遞迴(recursively)的方式,把多層的陣列攤平。 想得美

const arr = [1, 2, 3];
arr.concat([4, 5], 6); // [1,2,3,4,5,6]; 
arr.concat([7, [8, 9]]); // [ 1, 2, 3, 7, [ 8, 9 ] ]

拷貝拷的沒那麼深的 concat()

看到網路上討論到,使用concat()時,如果沒有給參數,就相當是原陣列與一個空陣列拼接,返回的原陣列,就算是原陣列的深拷貝。
但是利用concat()來複製陣列,只限用在結構較簡單的陣列上,如果運用在比較複雜與多層的物件上,這個方法就行不通了。

let arr = ["hi","wow",["O","X"]]
let arr2 = arr.concat();

// 試著修改第一層和第二層的陣列元素
arr[2][0]="OOO"
arr[0] = "Hello"

arr; // ["Hello", "wow", ["OOO", "X"]]
arr2; //["hi", "wow", ["OOO", "X"]]

我們可以觀察到,如果修改第一層的arr[0]這個元素為"Hello"arr2[0]並沒有被修改到,但是當我們修改arr[2][0]"OOO"的時候,arr2[2][0]也會跟著改成"OOO"。如果要拿concat()來複製物件型態的資料時,還是要特別注意這點。

push() 說 你會的我也會,且比你更會!

還記得我們前幾篇有介紹,從陣列尾端來「新增」元素的push()方法嗎?看起來push()做的事和concat()很像,都是從陣列的尾端加東西,不同之處在哪裡?

concat() 從原陣列複製一個新的陣列,在新陣列上進行操作,不會改變原陣列的值。 會拆開參數,把元素加進去
push() 在原陣列上修改,執行push()原陣列的值也會變 參數是陣列時,把整個陣列參數作為一個元素

其餘參數說 你們會的我更會!

還有另外一種方式可以達到和concat()一樣效果的我們把其餘參數(rest parameter),這個方式也很方便,效果也一樣。

const warmColor = ["red", "yellow"]
const coldColor = ["blue", "gray"]

// 使用 concat()
const allColor1 = [].concat(warmColor, coldColor);
// [ 'red', 'yellow', 'blue', 'gray' ]

// 也可以寫成
const allColor2 = warmColor.concat(coldColor);
// [ 'red', 'yellow', 'blue', 'gray' ]

const allColor3 = [...warmColor, ...coldColor];
// [ 'red', 'yellow', 'blue', 'gray' ]

但據說還是有些許不一樣,我們有機會再好好的測試。 機會?鐵人賽後吧

這三種吃小菜的方法:push()concat()和其餘參數(rest parameter)大家喜歡哪一種?
希望這幾天的小菜,可以讓大家至少對如何刪除或增加陣列的方法有一個概觀,路還很長、小菜還很多樣,還請大家慢慢品嚐囉。

如有需要改進的地方,拜託懇求請告知,我會盡量快速度修改,感謝您~


上一篇
JS 從陣列 Array 的開頭刪除元素
下一篇
輕鬆淺拷貝的陣列 Array 方法 slice()
系列文
JavaScript之一定要了解的 Array 與方法34
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

2 則留言

0
kkdayy_55330
iT邦新手 5 級 ‧ 2019-12-30 21:45:37

嗨大師你好~

warmColor應該沒定義吧?

tsuifei iT邦新手 4 級 ‧ 2020-01-04 06:29:46 檢舉

歐歐,偶不是大師啦~
你說的定義,是指 const warmColor = ["red", "yellow"] 這個嗎?

恩是的,但感覺應該是你寫的時候的一種個人習慣拉XD

0
cheerfulkid74
iT邦新手 5 級 ‧ 2020-06-22 14:26:48

原來法國的火車會這樣 XD 好有趣

tsuifei iT邦新手 4 級 ‧ 2020-07-29 04:54:01 檢舉

是滴,應該說歐洲很多的火車都這樣,因為地大,所以經過的城鎮很多,所以如果不斷頭斷尾,拉著這麼多車廂應該蠻耗效能的~

我要留言

立即登入留言